<template>
  <view
    :id="slideContainerRectID"
    class="tn-slide-verify"
    :class="[wrapperClass]"
    :style="wrapperStyle"
  >
    <!-- 中间提示文字 -->
    <view class="tips">
      {{ tipsText }}
    </view>

    <!-- 已激活的进度 -->
    <view
      class="active tn-flex-center"
      :class="[activeClass]"
      :style="activeStyle"
    >
      <view v-if="isPass" class="active-tips">{{ successTipsText }}</view>
    </view>

    <!-- 滑块 -->
    <view
      :id="slideRectID"
      class="slide tn-flex-center"
      :style="slideStyle"
      @touchstart="slideStartTouchEvent"
      @touchmove.prevent="slideTouchMoveEvent"
      @touchend="slideTouchEndEvent"
    >
      <view
        class="icon"
        :class="[{
          'animation': !isPass
        }]"
      >
        <tn-icon v-if="!isPass" :icon="icon"></tn-icon>
        <tn-icon v-else :icon="successIcon"></tn-icon>
      </view>
    </view>
  </view>
</template>

<script lang="ts" setup>
import {
  computed,
  watchEffect,
  CSSProperties,
  getCurrentInstance,
  ComponentInternalInstance,
  onMounted,
watch
} from 'vue'
import {
  slideVerifyProps,
  slideVerifyEmits
} from '../../../types/tn-slide-verify'
import { ColorInfo } from '../../../types/tuniao-ui'

import { handleValueWithUnit } from '@/tuniao-ui/utils'

import useComponentColor from '../../../libs/hooks/useComponentColor'
import useTouchEvent from '../lib/useTouchEvent'

import TnIcon from '../../tn-icon/src/Icon.vue'

const instance = getCurrentInstance() as ComponentInternalInstance

const props = defineProps(slideVerifyProps)
const emits = defineEmits(slideVerifyEmits)

const { generateColorInfo, splitColorInfo } = useComponentColor()
let componentColorInfo = generateColorInfo(props?.color || '', props?.bgColor || '')
// 监听颜色变化实时修改颜色对应的属性
watchEffect(() => {
  componentColorInfo = generateColorInfo(props?.color || '', props?.bgColor || '')
})

// 解析激活时颜色
const activeBgColor = computed<ColorInfo>(() => {
  return splitColorInfo('bg', props?.activeBgColor || '')
})

const {
  slideContainerRectID,
  slideRectID,
  slideWrapperRect,
  slideRect,
  distance,
  isPass,
  initRectInfo,
  slideStartTouchEvent,
  slideTouchMoveEvent,
  slideTouchEndEvent,
  resetSlideStatus
} = useTouchEvent(instance)

// 进度条样式
const wrapperStyle = computed<CSSProperties>(() => {
  let style: CSSProperties = {}
  if (props.width) {
    style.width = handleValueWithUnit(props.width)
  }
  if (props.height) {
    style.height = handleValueWithUnit(props.height)
  }
  if (props.fontSize) {
    style.fontSize = handleValueWithUnit(props.fontSize)
  }
  if (componentColorInfo.style.backgroundColor) {
    style.backgroundColor = componentColorInfo.style.backgroundColor
  }
  if(componentColorInfo.style.color) {
    style.color = componentColorInfo.style.color
  }
  return Object.assign(style, props.customStyle)
})

// 滑块样式
const slideStyle = computed<CSSProperties>(() => {
  let style: CSSProperties = {}
  if (props.height) {
    style.height = `calc(${handleValueWithUnit(props.height)} - 10rpx)`
    style.width = style.height
  }
  style.left = `calc(${distance.value.x}px + 5rpx)`
  return style
})

// 已激活的样式
const activeStyle = computed<CSSProperties>(() => {
  let style: CSSProperties = {}
  if (activeBgColor.value.type === 'style') {
    style.backgroundColor = activeBgColor.value.value
  }
  let width: number = distance.value.x
  if (width >= (slideWrapperRect.width - slideRect.width - 5)) {
    width = slideWrapperRect.width
  }
  style.width = `${width}px`
  return style
})

// 滑动条对应的类
const wrapperClass = computed<string>(() => {
  let clazz: string[] = []

  if (componentColorInfo.class.length > 0) {
    clazz.push(...componentColorInfo.class)
  }
  // disabled
  if (props.disabled) {
    clazz.push('disabled')
  }
  return clazz.join(' ')
})

// 已激活对应的类
const activeClass = computed<string>(() => {
  let clazz: string[] = []
  if (activeBgColor.value.type === 'class') {
    clazz.push(activeBgColor.value.value)
  }
  return clazz.join(' ')
})

// 监听是否滑动成功
watch(() => isPass.value, (val: boolean) => {
  if (val) {
    emits('success')
  }
})

// 重置验证状态
const reset = () => {
  resetSlideStatus()
}

onMounted(() => {
  initRectInfo()
})

defineExpose({
  reset
})
</script>

<style lang="scss" scoped>

  @import '../../../theme.scss';
  .tn-slide-verify {
    position: relative;
    width: 100%;
    height: 80rpx;
    background-color: #EFEFEF;
    color: #AAAAAA;
    overflow: hidden;

    .tips {
      position: absolute;
      z-index: 1;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);

      &::after {
        content: '';
        position: absolute;
        left: 0;
        top: 50%;
        height: 80%;
        width: 2rpx;
        transform: translateY(-50%);
        background-color: rgba(255, 255, 255, 0.8);
        box-shadow: 0rpx 0rpx 8rpx 4rpx rgba(255, 255, 255, 0.8);
        animation: sweepAnimation 2s ease-out infinite;
      }
    }

    .active {
      position: absolute;
      width: 0px;
      height: 100%;
      left: 0;
      top: 0;
      background-color: map-get(map-get($tn-color-map, 'green'), 'normal');
      z-index: 1;
      color: #FFFFFF;
      background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
      background-size: 80rpx 80rpx;
      animation: progress-striped 2s linear infinite;
    }

    .slide {
      position: absolute;
      height: 70rpx;
      width: 70rpx;
      box-sizing: border-box;
      background-color: #FFFFFF;
      top: 50%;
      left: 5rpx;
      transform: translateY(-50%);
      z-index: 10;

      .icon {
        position: relative;
        font-size: 46rpx;
        line-height: 1;
        &.animation {
          transform: translateX(-5%);
          animation: panAnimation 2s linear infinite alternate;
        }
      }
    }
  }

  @keyframes sweepAnimation {
    0% {
      left: 0;
    }
    100% {
      left: 100%;
    }
  }

  @keyframes panAnimation {
    0% {
      transform: translateX(-5%);
    }
    100% {
      transform: translateX(5%);
    }
  }

  @keyframes progress-striped {
  0% {
    background-position: 0 0;
  }
  100% {
    background-position: 80rpx 0;
  }
}
</style>
